package org.lex.game.sudoku.util;

import java.awt.Component;
import java.awt.Container;
import java.awt.Window;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;

import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JComboBox;
import javax.swing.JList;
import javax.swing.LookAndFeel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;

public class InstalledLookAndFeelsComboBox extends JComboBox<LookAndFeelInfo> {
	private static final long serialVersionUID = 7124328376663747302L;

	public InstalledLookAndFeelsComboBox() {
		super();
		this.initialize();
	}

	public LookAndFeelInfo getSelectedLookAndFeel() {
		return (LookAndFeelInfo) this.getSelectedItem();
	}

	private void updateLookAndFeel() {
		LookAndFeelInfo selected = getSelectedLookAndFeel();
		if (null != selected) {
			Container root = SwingUtilities.getAncestorOfClass(Window.class, InstalledLookAndFeelsComboBox.this);
			updateAllComponentsLookAndFeel(selected, root);
		}
	}

	private void initialize() {
		LookAndFeelInfo[] allLnfs = UIManager.getInstalledLookAndFeels();
		DefaultComboBoxModel<LookAndFeelInfo> model = new DefaultComboBoxModel<LookAndFeelInfo>(allLnfs);
		this.setModel(model);
		LookAndFeel currentLnf = UIManager.getLookAndFeel();
		if (null != currentLnf) {
			String className = currentLnf.getClass().getCanonicalName();
			for (LookAndFeelInfo info : allLnfs) {
				if (info.getClassName().equals(className)) {
					this.setSelectedItem(info);
					break;
				}
			}
		}
		this.addItemListener(new ItemListener() {
			@Override
			public void itemStateChanged(ItemEvent e) {
				if (ItemEvent.SELECTED == e.getStateChange()) {
					updateLookAndFeel();
				}
			}
		});
		this.setRenderer(new DefaultListCellRenderer() {
			private static final long serialVersionUID = -1852344390751370706L;

			@Override
			public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected,
					boolean cellHasFocus) {
				String text = "";
				if (value instanceof LookAndFeelInfo) {
					text = ((LookAndFeelInfo) value).getName();
				} else {
					text = null == value ? "(unkown)" : value.toString();
				}
				return super.getListCellRendererComponent(list, text, index, isSelected, cellHasFocus);
			}
		});
	}

	private static void updateAllComponentsLookAndFeel(LookAndFeelInfo lookAndFeel, Component... components) {
		if (null == components) {
			components = Window.getWindows();
		}
		updateLookAndFeel(lookAndFeel, components);
	}

	private static void updateLookAndFeel(final LookAndFeelInfo lookAndFeel, final Component... components) {
		if (null == lookAndFeel) {
			return;
		}
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				try {
					UIManager.setLookAndFeel(lookAndFeel.getClassName());
					if (null == components || 0 == components.length)
						return;
					for (Component c : components)
						if (null != c)
							SwingUtilities.updateComponentTreeUI(c);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}
}
